package com.tasks.positions.domain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

/**
 * Each position uniqueness is guaranteed by positionId which is a combination
 * of trading account and security id.
 * 
 * Note: Position may contain multiple trades with the same id but the version
 * must different.
 */
public class Position {
	private final static Logger LOGGER = Logger.getLogger(Position.class
			.getName());

	/**
	 * This is a combination of account and security id
	 */
	private final PositionId positionId;

	/**
	 * The trade id is a key and the trade event with the highest version within
	 * this position as a value.
	 */
	private final Map<Integer, TradeEvent> tradesMap;

	public Position(PositionId positionId) {
		this.positionId = positionId;

		this.tradesMap = new HashMap<Integer, TradeEvent>();
	}

	/**
	 * Add new trade event to the position.
	 * 
	 * Note: The trade events with the same id will be replaced with the trade
	 * event with the higher version.
	 * 
	 * @param newTradeEvent
	 *            the new trade event.
	 */
	public void addTrade(TradeEvent newTradeEvent) {
		LOGGER.info("Calling the addTrade: " + positionId
				+ " trade event: " + newTradeEvent);

		if (tradesMap.containsKey(newTradeEvent.getId())) {
			TradeEvent existingTrade = tradesMap.get(newTradeEvent.getId());

			if (existingTrade.getVersion() < newTradeEvent.getVersion()) {
				LOGGER.info("Updating the existing trade event with the new version: "
						+ positionId + " trade event: " + newTradeEvent);

				tradesMap.put(newTradeEvent.getId(), newTradeEvent);
			} else {
				LOGGER.info("Ignoring the trade event since the newer version exists: "
						+ positionId + " trade event: " + newTradeEvent);
			}
		} else {
			LOGGER.info("Adding the trade event: " + positionId
					+ " trade event: " + newTradeEvent);

			tradesMap.put(newTradeEvent.getId(), newTradeEvent);
		}
	}

	public boolean isTradeExists(int tradeId) {
		return tradesMap.containsKey(tradeId);
	}

	public PositionId getPositionId() {
		return positionId;
	}

	/**
	 * Gets all trade events for this position.
	 * 
	 * @return the list of all trade events which belong to the current
	 *         position.
	 */
	public List<TradeEvent> getAllTrades() {
		return new ArrayList<TradeEvent>(tradesMap.values());
	}
}
